package com.woniuxy.core.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniuxy.core.mapper.RunMapper;
import com.woniuxy.core.service.RunService;
import com.woniuxy.entity.AllRun;
import com.woniuxy.entity.AllUser;
import com.woniuxy.entity.DTO.GrabEvent;
import com.woniuxy.entity.DTO.RunPostMessageDTO;
import com.woniuxy.entity.OrderRun;
import com.woniuxy.entity.VO.RunPostMessageVO;
import com.woniuxy.util.PageResult;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class RunServiceImpl implements RunService {
    @Autowired
    private RunMapper runMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    private static final String RUN_PREFIX = "RUN";

    @Override
    public PageResult getListAll(RunPostMessageVO runPostMessageVO) {
        PageHelper.startPage(runPostMessageVO.getPageNum(),runPostMessageVO.getPageSize());
        List<RunPostMessageDTO> list = runMapper.getAll(runPostMessageVO.getState()
                ,runPostMessageVO.getUserId(),runPostMessageVO.getTakeUserId());
        PageInfo info = new PageInfo<>(list);
        PageResult pageResult = new PageResult();
        pageResult.setTotal(info.getTotal());
        pageResult.setList(info.getList());
        pageResult.setPageNum(info.getPageNum());
        pageResult.setPageSize(info.getPageSize());
        return pageResult;
    }

    @Override
    @Transactional
    public void pubRun(AllRun allRun) {
        try {
            String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
            allRun.setRunNumber(RUN_PREFIX+uuid);
            allRun.setCreateTime(LocalDateTime.now());
            // 计算时间差（秒）
            long expireSeconds = Duration.between(allRun.getCreateTime(), allRun.getDeadline()).getSeconds();
            // 添加Redis库存（带过期时间）
            String stock_key = "stock:" + allRun.getRunNumber();
            redisTemplate.opsForValue().set(
                    stock_key,
                    "1",
                    expireSeconds, // 过期时长数值
                    TimeUnit.SECONDS // 时间单位（秒）
            );
            //添加数据库
            runMapper.addRun(allRun);
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("发布失败");
        }
    }

    @Override
    public Boolean acceptRun(String runNumber, Integer userId) {
        //用Redis实现抢单操作
        String stockKey = "stock:" + runNumber;
        String userKey = "accepted_users:" + runNumber +":"+ userId;
        //lua脚本
        String luaScript = "local stock_key = KEYS[1]\n" +
                "local user_key = KEYS[2]\n" +
                "local stock = tonumber(redis.call('get',stock_key))\n" +
                "if stock == nil or stock <= 0 then \n" +
                "return -1\n" +
                "end\n" +
                "if redis.call('sismember',user_key,ARGV[1]) == 1 then\n" +
                "return 0\n" +
                "end\n" +
                "redis.call('decr',stock_key)\n" +
                "redis.call('sadd',user_key,ARGV[1])\n" +
                "return 1";
        RedisScript<Long> script = RedisScript.of(luaScript, Long.class);
        Object result = redisTemplate.execute(
                script,
                Arrays.asList(stockKey, userKey),
                userId.toString()
        );
        if (result.toString().equals("1")){
            return true;
        }
        return false;
    }

    // 生产者
    public void sendGrabEvent(GrabEvent grabEvent) {
        rabbitTemplate.convertAndSend(
                "directExchange",
                "a",
                grabEvent,
                message -> {
                    // 设置消息ID用于幂等
                    message.getMessageProperties()
                            .setMessageId(UUID.randomUUID().toString());
                    return message;
                }
        );
    }

    @Override
    public AllRun getById(Integer id) {
        AllRun allRun = runMapper.getRunById(id);
        return allRun;
    }

    @Override
    public void updateState(Integer id) {
        runMapper.updateState(id);
    }


}
